`timescale 1ns/1ns
`define DATA_WIDTH 256

module ZADDC_coz(input clk,
				 input rst_n,
				 input enable,
				 input MM_end_flag,
				 output reg MM_enable,
				 output reg func,
				 output reg [21:0] r_sel,
				 output reg [7:0] M_sel_a,
				 output reg [7:0] M_sel_b,
				 output reg [7:0] A_sel_a,
				 output reg [7:0] A_sel_b,
				 output reg end_flag
				);
				
reg [23:0] state,next_state;

parameter IDLE  = 24'b0000_0000_0000_0000_0000_0001,
          STEP1 = 24'b0000_0000_0000_0000_0000_0010,     
		  STEP2 = 24'b0000_0000_0000_0000_0000_0100,
		  STEP3 = 24'b0000_0000_0000_0000_0000_1000,
		  STEP4 = 24'b0000_0000_0000_0000_0001_0000,
		  STEP5 = 24'b0000_0000_0000_0000_0010_0000,
		  STEP6 = 24'b0000_0000_0000_0000_0100_0000,
		  STEP7 = 24'b0000_0000_0000_0000_1000_0000,
		  STEP8 = 24'b0000_0000_0000_0001_0000_0000,
		  STEP9 = 24'b0000_0000_0000_0010_0000_0000,
		  STEP10= 24'b0000_0000_0000_0100_0000_0000,
		  STEP11= 24'b0000_0000_0000_1000_0000_0000,
		  STEP12= 24'b0000_0000_0001_0000_0000_0000,
		  STEP13= 24'b0000_0000_0010_0000_0000_0000,
		  STEP14= 24'b0000_0000_0100_0000_0000_0000,
		  STEP15= 24'b0000_0000_1000_0000_0000_0000,
		  STEP16= 24'b0000_0001_0000_0000_0000_0000,
		  STEP17= 24'b0000_0010_0000_0000_0000_0000,
		  STEP18= 24'b0000_0100_0000_0000_0000_0000,
		  STEP19= 24'b0000_1000_0000_0000_0000_0000,
		  STEP20= 24'b0001_0000_0000_0000_0000_0000,
		  STEP21= 24'b0010_0000_0000_0000_0000_0000,
		  STEP22= 24'b0100_0000_0000_0000_0000_0000,
		  STEP23= 24'b1000_0000_0000_0000_0000_0000;
		  
always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		state <= IDLE;
	end
	else
	begin
		state <= next_state;
	end
end

always @(*)
begin
	case(state)
	IDLE   :
			begin
				if((enable) & (!end_flag))
					next_state = STEP1;
				else
					next_state = IDLE;
			end
	STEP1  :
			begin
					next_state = STEP2;

			end
	STEP2  :
			begin
				if(MM_end_flag)
					next_state = STEP3;
				else
					next_state = STEP2;
			end
	STEP3  :
			begin
				if(MM_end_flag)
					next_state = STEP4;
				else
					next_state = STEP3;
			end
	STEP4  :
			begin
				if(MM_end_flag)
					next_state = STEP5;
				else
					next_state = STEP4;
			end	
	STEP5  :
		 	begin
				if(MM_end_flag)
					next_state = STEP6;
				else
					next_state = STEP5;
			end	
	STEP6  :
		 	begin
					next_state = STEP7;
			end	
	STEP7  :
			begin
					next_state = STEP8;
			end		
	STEP8  :
			begin
					next_state = STEP9;
			end	
	STEP9  :
			begin
				if(MM_end_flag)
					next_state = STEP10;
				else
					next_state = STEP9;
			end	
	STEP10 :
			begin
					next_state = STEP11;
			end	
	STEP11 :
			begin
					next_state = STEP12;
			end
	STEP12 :
			begin
				next_state = STEP13;
			end
	STEP13 :
			begin
				if(MM_end_flag)
					next_state = STEP14;
				else
					next_state = STEP13;
			end	
	STEP14 :
			begin
					next_state = STEP15;
			end	
	STEP15 :
			begin
					next_state = STEP16;
			end
	STEP16 :
			begin
					next_state = STEP17;
			end
	STEP17 :
			begin
					next_state = STEP18;
			end
	STEP18 :
			begin
				if(MM_end_flag)
					next_state = STEP19;
				else
					next_state = STEP18;
			end
	STEP19 :
			begin
					next_state = STEP20;
			end
	STEP20 :
			begin
					next_state = STEP21;
			end
	STEP21 :
			begin
					next_state = STEP22;
			end
	STEP22 :
			begin
				if(MM_end_flag)
					next_state = STEP23;
				else
					next_state = STEP22;
			end
	STEP23 :
			begin
					next_state = IDLE;
			end
	default:
			begin
					next_state = IDLE;
			end
	endcase
end

always @(*)
begin
		case(state)
		/*
		IDLE:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		*/
		STEP1:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_1_0;
				A_sel_b = 8'b0_0_0_1_0_0_0_0;
			end
		STEP2:
			begin
				M_sel_a = 8'b0_1_0_0_0_0_0_0;
				M_sel_b = 8'b0_1_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP3:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_1_0;
				M_sel_b = 8'b0_1_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP4:
			begin
				M_sel_a = 8'b0_1_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_1_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_1_0_0;
				A_sel_b = 8'b0_0_1_0_0_0_0_0;
			end
		STEP5:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_1_0;
				M_sel_b = 8'b0_0_0_0_0_0_1_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP6:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_1_0_0_0_0;
				A_sel_b = 8'b1_0_0_0_0_0_0_0;
			end
		STEP7:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_1_0_0_0_0;
				A_sel_b = 8'b0_1_0_0_0_0_0_0;
			end
		STEP8:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_1_0_0;
				A_sel_b = 8'b0_0_1_0_0_0_0_0;
			end
		STEP9:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_1_0;
				M_sel_b = 8'b0_0_0_0_0_0_1_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP10:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_1_0;
				A_sel_b = 8'b1_0_0_0_0_0_0_0;
			end
		STEP11:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_1_0;
				A_sel_b = 8'b0_1_0_0_0_0_0_0;
			end
		STEP12:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_1_0_0_0_0_0_0;
				A_sel_b = 8'b1_0_0_0_0_0_0_0;
			end
		STEP13:
			begin
				M_sel_a = 8'b0_1_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_1_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP14:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_1_0_0;
				A_sel_b = 8'b0_0_1_0_0_0_0_0;
			end
		STEP15:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_1_0_0_0_0_0;
				A_sel_b = 8'b0_0_1_0_0_0_0_0;
			end
		STEP16:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_1_0_0;
				A_sel_b = 8'b0_0_1_0_0_0_0_0;
			end
		STEP17:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b1_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_1_0_0_0_0;
			end
		STEP18:
			begin
				M_sel_a = 8'b0_0_1_0_0_0_0_0;
				M_sel_b = 8'b1_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP19:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_1_0_0_0_0_0;
				A_sel_b = 8'b0_1_0_0_0_0_0_0;
			end
		STEP20:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_1_0_0_0_0;
				A_sel_b = 8'b1_0_0_0_0_0_0_0;
			end
		STEP21:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b1_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_1_0;
			end
		STEP22:
			begin
				M_sel_a = 8'b0_0_0_0_0_1_0_0;
				M_sel_b = 8'b1_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		STEP23:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_1_0_0;
				A_sel_b = 8'b0_1_0_0_0_0_0_0;
			end
		default:
			begin
				M_sel_a = 8'b0_0_0_0_0_0_0_0;
				M_sel_b = 8'b0_0_0_0_0_0_0_0;
				A_sel_a = 8'b0_0_0_0_0_0_0_0;
				A_sel_b = 8'b0_0_0_0_0_0_0_0;
			end
		endcase
end

always @(*)
begin
		case(state)
		/*
		IDLE  : 
			 	r_sel = 22'b0;
		*/
		STEP1 :
				r_sel = 22'b000_01_000_000_000_000_000_00;
		STEP2 :
				r_sel = 22'b000_10_000_000_000_000_000_00;
		STEP3 :
				r_sel = 22'b010_00_000_000_000_000_000_00;
		STEP4 :
				r_sel = 22'b000_10_000_000_000_000_001_00;
		STEP5 :
			 	r_sel = 22'b000_00_000_010_000_000_000_00;
		STEP6 :
				r_sel = 22'b000_00_000_001_000_000_000_00;
		STEP7 :
				r_sel = 22'b000_00_000_001_000_000_000_00;
		STEP8 :
				r_sel = 22'b000_00_000_000_000_000_001_00;
		STEP9 :
				r_sel = 22'b000_00_000_000_000_000_010_00;
		STEP10:
				r_sel = 22'b000_00_000_000_000_000_001_00;
		STEP11:
				r_sel = 22'b000_00_000_000_000_000_001_00;
		STEP12:
				r_sel = 22'b000_01_000_000_000_000_000_00;
		STEP13:
				r_sel = 22'b000_10_000_000_000_000_000_00;
		STEP14:
				r_sel = 22'b000_00_000_000_000_001_000_00;
		STEP15:
			 	r_sel = 22'b000_00_001_000_000_000_000_00;
		STEP16:
				r_sel = 22'b000_00_001_000_000_000_000_00;
		STEP17:
				r_sel = 22'b001_00_000_000_000_000_000_00;
		STEP18:
				r_sel = 22'b000_00_010_000_000_000_000_00;
		STEP19:
				r_sel = 22'b000_00_001_000_000_000_000_00;
		STEP20:
				r_sel = 22'b001_00_000_000_000_000_000_00;
		STEP21:
				r_sel = 22'b001_00_000_000_000_000_000_00;
		STEP22:
				r_sel = 22'b000_00_000_000_000_010_000_00;
		STEP23:
				r_sel = 22'b000_00_000_000_000_001_000_00;
		default:
				r_sel = 22'b0;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		MM_enable <= 1'b0;
	end
	else
	begin
		case(next_state)
		IDLE  :
					MM_enable <= 1'b0;
		STEP1 :
					MM_enable <= 1'b0;
		STEP2 :
				if(state == STEP1)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP3 :
				if(state == STEP2)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP4 :
				if(state == STEP3)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP5 :
				if(state == STEP4)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP6 :
					MM_enable <= 1'b0;
		STEP7 :
					MM_enable <= 1'b0;
		STEP8 :
					MM_enable <= 1'b0;
		STEP9 :
				if(state == STEP8)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP10:
					MM_enable <= 1'b0;
		STEP11:
					MM_enable <= 1'b0;
		STEP12:
					MM_enable <= 1'b0;
		STEP13:
				if(state == STEP12)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP14:
					MM_enable <= 1'b0;
		STEP15:
					MM_enable <= 1'b0;
		STEP16:
					MM_enable <= 1'b0;
		STEP17:
					MM_enable <= 1'b0;
		STEP18:
				if(state == STEP17)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP19:
					MM_enable <= 1'b0;
		STEP20:
					MM_enable <= 1'b0;
		STEP21:
					MM_enable <= 1'b0;
		STEP22:
				if(state == STEP21)
					MM_enable <= 1'b1;
				else
					MM_enable <= 1'b0;
		STEP23:
					MM_enable <= 1'b0;
		default:
					MM_enable <= 1'b0;
		endcase
	end
end

always @(*)
begin
		case(state)
		/*
		IDLE  :
					func = 1'b0;
		*/
		STEP1 :
					func = 1'b1;
		/*
		STEP2 :
					func = 1'b0;
		STEP3 :
					func = 1'b0;
		STEP4 :
					func = 1'b0;
		STEP5 :
					func = 1'b0;	
		*/
		STEP6 :	
					func = 1'b1;
		STEP7 :
					func = 1'b1;
		STEP8 :
					func = 1'b1;
		/*
		STEP9 :
					func = 1'b0;
		*/
		STEP10:
					func = 1'b1;					
		STEP11:
					func = 1'b1;
		STEP12:
					func = 1'b1;
		/*	
		STEP13:
					func = 1'b0;	
		*/
		STEP14:
					func = 1'b1;
		/*
		STEP15:
					func = 1'b0;
		STEP16:
					func = 1'b0;
		*/
		STEP17:
					func = 1'b1;
		/*
		STEP18:
					func = 1'b0;
		STEP19:
					func = 1'b0;		
		STEP20:
					func = 1'b0;
		*/					
		STEP21:
					func = 1'b1;
		/*
		STEP22:
					func = 1'b0;	
		STEP23:
					func = 1'b0;	
		*/
		default:
					func = 1'b0;
		endcase
end

always @(posedge clk or negedge rst_n)
begin
	if(!rst_n)
	begin
		end_flag <= 1'b0;
	end
	else if(state == STEP23)
	begin
		end_flag <= 1'b1;
	end
	else
	begin
		end_flag <= 1'b0;
	end
end

endmodule
